package com.zh.javaguide.threadlocal;


import java.text.SimpleDateFormat;
import java.util.Random;

/**
 * 实现每⼀个线程都有⾃⼰的专属本地变量
 *
 * 你创建了⼀个 ThreadLocal 变量，那么访问这个变量的每个线程都会有这个变量的本地副本
 *
 * 关键点
 * Thread
 * ThreadLocal
 * 存放当前threadLocal对象的map
 * ThreadLocal.ThreadLocalMap
 * 弱引用
 * static class Entry extends WeakReference<ThreadLocal<?>>
 * @date :2021/1/23 18:45
 */

public class ThreadLocalDemo1 implements Runnable {


	// SimpleDateFormat 不是线程安全的，所以每个线程都要有⾃⼰独⽴的副本
	private static final ThreadLocal<SimpleDateFormat> formatter = ThreadLocal.withInitial(()->new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));




	public static void main(String[] args) throws InterruptedException {
		ThreadLocalDemo1 localDemo1 = new ThreadLocalDemo1();
		for (int i = 0; i < 10; i++) {
			Thread thread = new Thread(localDemo1, "" + i);
			Thread.sleep(new Random().nextInt(1000));
			thread.start();
		}
	}

	@Override
	public void run() {
		System.out.println("Thread name = "+Thread.currentThread().getName()+"default Fommatter="+formatter.get().toPattern());

		try {
			Thread.sleep(new Random().nextInt(1000));
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		formatter.set(new SimpleDateFormat());
		System.out.println("thread Name="+Thread.currentThread().getName()+"formatter="+formatter.get().toPattern());

		//使用完threadlocal后最好remove()方法，防止出现内存泄漏
		formatter.remove();
 	}
	/**
	 * 结果：
	 * Thread name = 0default Fommatter=yyyy-MM-dd HH:mm:ss
	 * thread Name=0formatter=yy-M-d ah:mm
	 * Thread name = 1default Fommatter=yyyy-MM-dd HH:mm:ss
	 * Thread name = 2default Fommatter=yyyy-MM-dd HH:mm:ss
	 * thread Name=1formatter=yy-M-d ah:mm
	 * thread Name=2formatter=yy-M-d ah:mm
	 * Thread name = 3default Fommatter=yyyy-MM-dd HH:mm:ss
	 * thread Name=3formatter=yy-M-d ah:mm
	 * Thread name = 4default Fommatter=yyyy-MM-dd HH:mm:ss
	 * Thread name = 5default Fommatter=yyyy-MM-dd HH:mm:ss
	 * Thread name = 6default Fommatter=yyyy-MM-dd HH:mm:ss
	 * thread Name=5formatter=yy-M-d ah:mm
	 * Thread name = 7default Fommatter=yyyy-MM-dd HH:mm:ss
	 * thread Name=6formatter=yy-M-d ah:mm
	 * thread Name=4formatter=yy-M-d ah:mm
	 * Thread name = 8default Fommatter=yyyy-MM-dd HH:mm:ss
	 * thread Name=7formatter=yy-M-d ah:mm
	 * Thread name = 9default Fommatter=yyyy-MM-dd HH:mm:ss
	 * thread Name=8formatter=yy-M-d ah:mm
	 * thread Name=9formatter=yy-M-d ah:mm
	 *
	 * 结论：Thread-0已经改变了formatter的值，但仍然是thread-2默认格式化程序与初始化值相同
	 *  ThreadLocal 变量，那么访问这个变量的每个线程都会有这个变量的本地副本
	 *
	 */

}


